package com.ybe.session;


import java.security.SecureRandom;
import java.time.Instant;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;


public class SessionHolder {

    private static final int SESSION_KEY_LEN = 12; // letters & digits
    private static final char[] ALNUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".toCharArray();
    public static final long SESSION_TTL_MILLIS = TimeUnit.MINUTES.toMillis(10);

    public static ConcurrentHashMap<Integer, Session> sessionsWithCustomer  = new ConcurrentHashMap<>();
    public static ConcurrentHashMap<String, Session> sessionsWithKey   = new ConcurrentHashMap<>();

    public static ConcurrentHashMap<String, Session> getSessionsWithKey() {
        return sessionsWithKey;
    }

    public static void setSessionsWithKey(ConcurrentHashMap<String, Session> sessionsWithKey) {
        SessionHolder.sessionsWithKey = sessionsWithKey;
    }

    public static ConcurrentHashMap<Integer, Session> getSessionsWithCustomer() {
        return sessionsWithCustomer;
    }

    public static void setSessionsWithCustomer(ConcurrentHashMap<Integer, Session> sessionsWithCustomer) {
        SessionHolder.sessionsWithCustomer = sessionsWithCustomer;
    }

    public static void addSession(Session session) {
        sessionsWithCustomer.put(session.customerId, session);
        sessionsWithKey.put(session.key, session);
    }

    public static Session getSessionByKey(String key) {
        return sessionsWithKey.get(key);
    }

    public static Session getSessionById(Integer id) {
        return sessionsWithCustomer.get(id);
    }

    public static void removeSession(Session session) {
        sessionsWithCustomer.remove(session.customerId);
        sessionsWithKey.remove(session.key);
    }

    public static String genSessionKey() {
        SecureRandom rnd = new SecureRandom();
        char[] buf = new char[SESSION_KEY_LEN];
        for (int i = 0; i < buf.length; i++) {
            buf[i] = ALNUM[rnd.nextInt(ALNUM.length)];
        }
        return new String(buf);
    }


    public  static void removeExpiredSessions() {
        long now = System.currentTimeMillis();
        int removed = 0;
        for (Iterator<Map.Entry<Integer, Session>> it = SessionHolder.getSessionsWithCustomer().entrySet().iterator(); it.hasNext();) {
            Map.Entry<Integer, Session> e = it.next();
            Session s = e.getValue();
            if (s.isExpired(now)) {
                it.remove();
                SessionHolder.getSessionsWithKey().remove(s.getKey(), s);
                removed++;
            }
        }
        if (removed > 0) {
            System.out.println(Instant.ofEpochMilli(now) + " remove " + removed + " expired sessions");
        }
    }

}
